OpenRoads Designer CONNECT Edition SDK Help

Horizontal alignment reporter

Description

  • This is custom class for generating data related to horizontal alignments from current dgn.

  • ReportAllAlignments() and ReportSingleAlignment() functions creates data for alignments.

  • Data generated is based on element type such as line, spiral, arc.

Remarks

  • This sample code is a part of ManagedSDKExample which you get with SDK installation under "examples" section in SDK installation directory.

  • This code is simplified and does not include report generation code, but user can get it under ManagedSDKExample ->Examples ->HorizontalAlignmentReporter.

Source Code



//Required References
using System;
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.SDK;
using Bentley.CifNET.LinearGeometry;
using Bentley.CifNET.Formatting;

namespace ManagedSDKExample.Examples
{
    class HorizontalAlignmentReporter
    {
        internal static DgnModel m_activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
        internal static int LinearPrecision { get { return GetDesignFilePrecision(); } }

        // Report Options | Run on all alignments in active model 
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public void ReportAllAlignments()
        {
            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
            if (sdkCon == null)
                return;

            GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
            if (geomModel == null)
                return;

            // Cycle through Horizontal Alignments 
            foreach (Alignment al in geomModel.Alignments)
            {
                if (!al.IsFinalElement)
                    continue;

                ReportAlignment(al);
            }
        }

        // Report Options | Run on given alignment
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public void ReportSingleAlignment(Alignment al)
        {
            ReportAlignment(al);
        }

        // Utility Function | Read and display data for given alignment 
        /*--------------+---------------+---------------+---------------+---------------+------*/
        internal void ReportAlignment(Alignment al)
        {
            // Generate Alignment Header
            string name = "Unnamed", style = "";
            if (al.Name != null && al.Name != "")
                name = al.Name;
            if (al.FeatureName != null)
                style = al.FeatureName;

            // Report Elements in Alignment   
            LinearElement[] elements = { };
            try
            {
                LinearComplex alComplex = (LinearComplex)al.LinearGeometry;
                elements = alComplex.GetSubLinearElements();
            }
            catch
            {
                elements = new LinearElement[1];
                elements[0] = al.LinearGeometry;
            }

            AlignmentPropertyReader propReader = new AlignmentPropertyReader(al);
            foreach (LinearElement le in elements)
            {
                Dictionary<string, string> elementProperties = propReader.Read(le);
            }
        }

        // Report Options | Run on all alignments in active model 
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public void ReportAllAlignmentsItemTypes()
        {

            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
            if (sdkCon == null)
                return;

            GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
            if (geomModel == null)
                return;

            List<string> labels = new List<string>() { "Item Type Library Name", "Item Type Name", "Property Name", "Property Type", "Property Value" };

            DgnModel dgn = geomModel.DgnModel;
            DgnFile file = dgn.GetDgnFile();
            Dictionary<string, string> fileProperties = new Dictionary<string, string>();
            fileProperties.Add("Project", dgn.ModelName);
            fileProperties.Add("File Name", file.GetFileName());
            fileProperties.Add("Last Accessed", file.LastSaveTimeUtc.ToString());


            // Cycle through Horizontal Alignments 

            foreach (Alignment al in geomModel.Alignments)
            {
                if (!al.IsFinalElement)
                    continue;

                // Generate Alignment Header
                string name = string.IsNullOrEmpty(al.Name) ? "Unnamed" : al.Name;
                string style = string.IsNullOrEmpty(al.FeatureName) ? "No Feature Definition" : al.FeatureName;

                CustomItemHost host = new CustomItemHost(al.Element, true);
                if (host != null && host.CustomItemsCount > 0)
                {
                    List<string> data = new List<string>();
                    foreach (Bentley.DgnPlatformNET.DgnEC.IDgnECInstance instance in host.CustomItems)
                    {
                        data.Add(string.Format("{0}|{1}|||", instance.ClassDefinition.Schema.NamespacePrefix, instance.ClassDefinition.Name));

                        foreach (Bentley.ECObjects.Instance.IECPropertyValue propertyValue in instance)
                        {
                            string propertyType = propertyValue.Type.DisplayLabel;
                            string value = "";
                            if (propertyValue is Bentley.ECObjects.Instance.IECArrayValue)
                            {
                                Bentley.ECObjects.Instance.IECArrayValue ecArray = propertyValue as Bentley.ECObjects.Instance.IECArrayValue;
                                foreach (Bentley.ECObjects.Instance.IECPropertyValue arrayValue in ecArray.ContainedValues)
                                {
                                    if (arrayValue.ArrayIndex == 0)
                                    {
                                        propertyType = "Array&lt;" + arrayValue.Type.DisplayLabel + "&gt;";
                                    }
                                    value += GetFormattedPropertyValue(arrayValue);
                                    if (arrayValue.ArrayIndex < ecArray.Count - 1)
                                    {
                                        value += "<br />";
                                    }
                                }
                            }
                            else
                            {
                                value = GetFormattedPropertyValue(propertyValue);
                            }

                            data.Add(string.Format("||{0}|{1}|{2}", propertyValue.AccessString, propertyType, value));
                        }
                    }
                }

            }
        }

        // Utility Class | Reads properties from linear elements for horizontal alignments.
        /*--------------+---------------+---------------+---------------+---------------+------*/
        internal class AlignmentPropertyReader
        {
            private Alignment m_alignment;
            private StationingFormatter sFormatter;

            public AlignmentPropertyReader(Alignment al)
            {
                m_alignment = al;
                sFormatter = new StationingFormatter(m_alignment);
            }

            // Generic read function determines element type and passes to specific read function
            public Dictionary<string, string> Read(LinearElement le)
            {
                Dictionary<string, string> properties = new Dictionary<string, string>();

                if (le is Line)
                    properties = ReadLine(le as Line);
                else if (le is Spiral)
                    properties = ReadSpiral(le as Spiral);

                else if (le is CircularArc)
                    properties = ReadCircularArc(le as CircularArc);

                if (properties.Count == 0)
                    properties.Add("No properties read for element", le.GetType().Name);

                return properties;
            }

            // Reads Bentley.CifNET.LinearGeometry.Line
            internal Dictionary<string, string> ReadLine(Line line)
            {
                Dictionary<string, string> lineProperties = new Dictionary<string, string>();

                lineProperties.Add("Element", line.GetType().Name);
                lineProperties.Add("Start", GetStation(m_alignment, line.StartPoint.Coordinates) + " | " + FormatCoordinates(line.StartPoint));
                lineProperties.Add("End", GetStation(m_alignment, line.EndPoint.Coordinates) + " | " + FormatCoordinates(line.EndPoint));
                lineProperties.Add("Tangential Direction", FormatDirection(line.Direction));
                lineProperties.Add("Tangential Length", FormatDistance(line.Length));

                return lineProperties;
            }

            // Reads Bentley.CifNET.LinearGeometry.Spiral
            internal Dictionary<string, string> ReadSpiral(Spiral spiral)
            {
                Dictionary<string, string> spiralProperties = new Dictionary<string, string>();

                spiralProperties.Add("Element", spiral.SpiralType.ToString());
                spiralProperties.Add("Start", GetStation(m_alignment, spiral.StartPoint.Coordinates) + " | " + FormatCoordinates(spiral.StartPoint));
                Bentley.GeometryNET.DPoint3d pi = GetPI(spiral);
                spiralProperties.Add("SPI", GetStation(m_alignment, pi) + " | " + FormatCoordinates(pi));
                spiralProperties.Add("End", GetStation(m_alignment, spiral.EndPoint.Coordinates) + " | " + FormatCoordinates(spiral.EndPoint));
                spiralProperties.Add("Entrance Radius", FormatDistance(Math.Abs(spiral.StartRadius)));
                spiralProperties.Add("Exit Radius", FormatDistance(Math.Abs(spiral.EndRadius)));
                spiralProperties.Add("Length", FormatDistance(spiral.Length));
                spiralProperties.Add("Angle", FormatAngleDirection(spiral.SweepAngle));
                spiralProperties.Add("Constant", FormatNumber(spiral.Constant));
                spiralProperties.Add("Long Tangent", FormatDistance(spiral.LongTangent));
                spiralProperties.Add("Short Tangent", FormatDistance(spiral.ShortTangent));
                spiralProperties.Add("Long Chord", FormatDistance(spiral.LongChord));
                spiralProperties.Add("Xs", FormatNumber(spiral.Xs));
                spiralProperties.Add("Ys", FormatNumber(spiral.Ys));
                spiralProperties.Add("P", FormatNumber(spiral.PValue));
                spiralProperties.Add("K", FormatNumber(spiral.KValue));
                spiralProperties.Add("Tangent Direction (Start)", FormatDirection(spiral.StartPoint.TangentDirection));
                spiralProperties.Add("Radial Direction (Start)", GetRadialDirection(spiral.StartPoint));
                spiralProperties.Add("Chord Direction", GetChordDirection(spiral.StartPoint, spiral.EndPoint));
                spiralProperties.Add("Radial Direction (End)", GetRadialDirection(spiral.EndPoint));
                spiralProperties.Add("Tangent Direction (End)", FormatDirection(spiral.EndPoint.TangentDirection));

                return spiralProperties;
            }

            // Reads Bentley.CifNET.LinearGeometry.CircularArc
            internal Dictionary<string, string> ReadCircularArc(CircularArc arc)
            {
                Dictionary<string, string> arcProperties = new Dictionary<string, string>();

                arcProperties.Add("Element", arc.GetType().Name);
                arcProperties.Add("Start", GetStation(m_alignment, arc.StartPoint.Coordinates) + " | " + FormatCoordinates(arc.StartPoint));
                Bentley.GeometryNET.DPoint3d pi = GetPI(arc);
                arcProperties.Add("PI", Get_PI_Station(m_alignment, arc) + " | " + FormatCoordinates(pi));
                arcProperties.Add("CC", " | " + FormatCoordinates(arc.CenterPoint));
                arcProperties.Add("End", GetStation(m_alignment, arc.EndPoint.Coordinates) + " | " + FormatCoordinates(arc.EndPoint));
                arcProperties.Add("Radius", FormatDistance(Math.Abs(arc.Radius)));
                arcProperties.Add("Delta", FormatAngleDirection(arc.SweepAngle));
                arcProperties.Add("Degree of Curvature (Arc)", FormatDegreeOfCurve(arc.Radius));
                arcProperties.Add("Length", FormatDistance(arc.Length));
                arcProperties.Add("Tangent", FormatDistance(arc.TangentDistance));
                arcProperties.Add("Chord", FormatDistance(arc.ChordDistance));
                double delta = Math.Abs(arc.SweepAngle);
                arcProperties.Add("Middle Ordinate", FormatDistance((delta >= Math.PI) ? 0.0 : (Math.Abs(arc.Radius) * (1.0 - Math.Cos(0.5 * delta)))));
                arcProperties.Add("External", FormatDistance((delta > Math.PI) ? 0.0 : (Math.Abs(arc.TangentDistance) * Math.Tan(0.25 * delta))));
                arcProperties.Add("Tangent Direction (Start)", FormatDirection(arc.StartPoint.TangentDirection));
                arcProperties.Add("Radial Direction (Start)", GetRadialDirection(arc.StartPoint));
                arcProperties.Add("Chord Direction", GetChordDirection(arc.StartPoint, arc.EndPoint));
                arcProperties.Add("Radial Direction (End)", GetRadialDirection(arc.EndPoint));
                arcProperties.Add("Tangent Direction (End)", FormatDirection(arc.EndPoint.TangentDirection));

                return arcProperties;
            }
        }

        private string GetFormattedPropertyValue(Bentley.ECObjects.Instance.IECPropertyValue property)
        {
            if (Bentley.ECObjects.ECObjects.BooleanType == property.Type ||
                Bentley.ECObjects.ECObjects.IntegerType == property.Type ||
                Bentley.ECObjects.ECObjects.StringType == property.Type)
            {
                return property.StringValue;
            }
            else if (Bentley.ECObjects.ECObjects.DateTimeType == property.Type)
            {
                DateTime? dateTime = property.NativeValue as DateTime?;
                if (dateTime.HasValue)
                {
                    return dateTime.ToString();
                }
            }
            else if (Bentley.ECObjects.ECObjects.DoubleType == property.Type)
            {
                return FormatNumber(property.DoubleValue);
            }
            else if (Bentley.ECObjects.ECObjects.PointType == property.Type)
            {
                Bentley.GeometryNET.DPoint3d? point = property.NativeValue as Bentley.GeometryNET.DPoint3d?;
                if (point.HasValue)
                {
                    return "[" + FormatNumber(point.Value.X) + ", " + FormatNumber(point.Value.Y) + "]";
                }
            }
            return string.Empty;
        }

        

        private static string GetStation(Alignment al, Bentley.GeometryNET.DPoint3d point)
        {
            LinearPoint stationPoint = al.LinearGeometry.ProjectPointOnPerpendicular(point);
           
            // Get numerical station
            string stationStr = "";
            double stationNum = stationPoint.DistanceOnExtension + stationPoint.DistanceAlong;

            // Format it
            StationingFormatter sformatter = new StationingFormatter(al);
            StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(m_activeModel);
            sformatter.FormatStation(ref stationStr, stationNum, settings);

            return stationStr;
        }

        public static string FormatCoordinates(LinearPoint point)
        {
            string y = FormatForDisplay.Coordinate(point.Coordinates.Y, m_activeModel);
            string y2 = FormatForDisplay.Coordinate(point.Coordinates.Y);
            string x = FormatForDisplay.Coordinate(point.Coordinates.X, m_activeModel);
            return "( " + y + ", " + x + " )";
        }
        public static string FormatCoordinates(Bentley.GeometryNET.DPoint3d point)
        {
            string y = FormatForDisplay.Coordinate(point.Y, m_activeModel);
            string x = FormatForDisplay.Coordinate(point.X, m_activeModel);
            return "( " + y + ", " + x + " )";
        }
        public static string FormatDirection(double value)
        {
            ModelInfo info = m_activeModel.GetModelInfo();
            return FormatForDisplay.Direction(value, m_activeModel);
        }
        public static string FormatDistance(double value)
        {
            return FormatForDisplay.Distance(value, m_activeModel, LinearPrecision);
        }
        public static string FormatNumber(double num)
        {
            return FormatForDisplay.Double(num);
        }

        /*------------------------------------------------------------------------------------**/
        /* Alignment property calculations
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public static Bentley.GeometryNET.DPoint3d GetPI(LinearElement le)
        {
            double x = 0.0, y = 0.0;

            if (le is Spiral)
            {
                Spiral spiral = le as Spiral;
                if (spiral.IsOutgoing)
                {
                    x = spiral.StartPoint.Coordinates.X + spiral.ShortTangent * Math.Cos(spiral.StartDirection);
                    y = spiral.StartPoint.Coordinates.Y + spiral.ShortTangent * Math.Sin(spiral.StartDirection);
                }
                else
                {
                    x = spiral.StartPoint.Coordinates.X + spiral.LongTangent * Math.Cos(spiral.StartDirection);
                    y = spiral.StartPoint.Coordinates.Y + spiral.LongTangent * Math.Sin(spiral.StartDirection);
                }
            }

            else if (le is CircularArc)
            {
                CircularArc arc = le as CircularArc;
                Bentley.GeometryNET.DPoint3d point;
                arc.PIPoint(out point);
                return point;
            }

            return new Bentley.GeometryNET.DPoint3d(x, y);
        }
        public static string FormatAngleDirection(double valueRadians)
        {
            string direction = (valueRadians > 0) ? "Left" : "Right";
            
            ModelInfo info = m_activeModel.GetModelInfo();
            string angle= FormatForDisplay.Angle(Math.Abs(valueRadians), m_activeModel);
            return angle + " " + direction;
        }

        public static string GetRadialDirection(LinearPoint point)
        {
            double direction = (point.TangentDirection - (Math.PI * 0.5)) % (2.0 * Math.PI);
            if (direction < 0)
                direction = (Math.PI * 2.0) + direction;
            return FormatDirection(direction);
        }
        public static string GetChordDirection(LinearPoint p1, LinearPoint p2)
        {
            double azimuth = 0.0;
            if (p1.Coordinates.X == p2.Coordinates.X)
                azimuth = (p2.Coordinates.Y >= p1.Coordinates.Y) ? 0.0 : Math.PI;
            double stagedValue = Math.Atan2(p2.Coordinates.X - p1.Coordinates.X, p2.Coordinates.Y - p1.Coordinates.Y);
            if (p2.Coordinates.X > p1.Coordinates.X)
                azimuth = stagedValue;
            else
                azimuth = stagedValue + 2.0 * Math.PI;

            double dDir = 0.5 * Math.PI - azimuth;
            return FormatDirection(dDir);
        }
        internal static string Get_PI_Station(Alignment al, CircularArc arc)
        {
            // Get numerical station
            string stationStr = "";
            LinearPoint startPoint = al.LinearGeometry.ProjectPointOnPerpendicular(arc.StartPoint.Coordinates);
            double stationNum = startPoint.DistanceOnExtension + startPoint.DistanceAlong + arc.TangentDistance;

            // Format it
            StationingFormatter sformatter = new StationingFormatter(al);
            StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(m_activeModel);
            sformatter.FormatStation(ref stationStr, stationNum, settings);

            return stationStr;
        }

        internal static int GetDesignFilePrecision()
        {
            int precision = 0;

            // Get the precision out of the PrecisionFormat enum
            PrecisionFormat lp = m_activeModel.GetModelInfo().LinearPrecision;
            string[] splitPrec = lp.ToString().Split('_');
            if (splitPrec.Length >= 2)
                int.TryParse(splitPrec[1], out precision);

            if (precision > 0)
                return precision;
            else
                return 3; // Default is 3
        }
        public static string FormatDegreeOfCurve(double radius)
        {
            ModelInfo info = m_activeModel.GetModelInfo();
            double radiusInMasterUnits = radius / (info.UorPerMaster / info.UorPerMeter);
            double valueRadians = 100.0 / (radiusInMasterUnits);
            return FormatForDisplay.Angle(valueRadians, m_activeModel);
        }
    }
}